﻿namespace FlexField.Metadata
{
    /// <summary>
    /// Provides an abstraction for a storage and management of metadata fields.
    /// </summary>
    /// <typeparam name="TKey">The type used for the primary key for the field.</typeparam>
    public interface IFieldStore<TKey> : IDisposable where TKey : IEquatable<TKey>
    {
        /// <summary>
        /// Creates a new metadata field in a store as an asynchronous operation.
        /// </summary>
        /// <param name="entityId">The primary key of the entity that the field belongs to.</param>
        /// <param name="field">The metadata field to create in the store.</param>
        /// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
        /// <returns>A <see cref="Task{TResult}"/> that represents the <see cref="MetadataResult"/> of the asynchronous query.</returns>
        Task<MetadataResult> CreateAsync(TKey entityId, MetadataField<TKey> field, CancellationToken cancellationToken);

        /// <summary>
        /// Updates a metadata field in a store as an asynchronous operation.
        /// </summary>
        /// <param name="entityId">The primary key of the entity that the field belongs to.</param>
        /// <param name="field">The metadata field to update in the store.</param>
        /// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
        /// <returns>A <see cref="Task{TResult}"/> that represents the <see cref="MetadataResult"/> of the asynchronous query.</returns>
        Task<MetadataResult> UpdateAsync(TKey entityId, MetadataField<TKey> field, CancellationToken cancellationToken);

        /// <summary>
        /// Deletes a metadata field from the store as an asynchronous operation.
        /// </summary>
        /// <param name="entityId">The primary key of the entity that the field belongs to.</param>
        /// <param name="field">The metadata field to delete from the store.</param>
        /// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
        /// <returns>A <see cref="Task{TResult}"/> that represents the <see cref="MetadataResult"/> of the asynchronous query.</returns>
        Task<MetadataResult> DeleteAsync(TKey entityId, MetadataField<TKey> field, CancellationToken cancellationToken);

        /// <summary>
        /// Finds the metadata field who has the specified ID as an asynchronous operation.
        /// </summary>
        /// <param name="fieldId">The field ID to look for.</param>
        /// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
        /// <returns>A <see cref="Task{TResult}"/> that result of the look up.</returns>
        Task<MetadataField<TKey>> FindByIdAsync(TKey fieldId, CancellationToken cancellationToken);

        /// <summary>
        /// Finds the metadata field who has the specified name as an asynchronous operation.
        /// </summary>
        /// <param name="entityId">The primary key of the entity that the field belongs to.</param>
        /// <param name="fieldName">The field name to look for.</param>
        /// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
        /// <returns>A <see cref="Task{TResult}"/> that result of the look up.</returns>
        Task<MetadataField<TKey>> FindByNameAsync(TKey entityId, string fieldName, CancellationToken cancellationToken);

        /// <summary>
        /// Returns a list of metadata fields associated with the specified property name and property value.
        /// </summary>
        /// <param name="entityId">The primary key of the entity that the fields belongs to.</param>
        /// <param name="propertyName">The name of the field property.</param>
        /// <param name="propertyValue">The value of the field property.</param>
        /// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
        /// <returns>A <see cref="Task{TResult}"/> that represents the result of the asynchronous query, a list of <see cref="MetadataField{TKey}"/> who contain the specified property.</returns>
        Task<IList<MetadataField<TKey>>> FindByPropertyAsync(TKey entityId, string propertyName, string propertyValue, CancellationToken cancellationToken);

        /// <summary>
        /// Gets a list of metadata fields that belong to the specified <paramref name="entityId"/>.
        /// </summary>
        /// <param name="entityId">The primary key of the entity that the fields belongs to.</param>
        /// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
        /// <returns>A <see cref="Task{TResult}"/> that represents the result of the asynchronous query, a list of <see cref="MetadataField{TKey}"/> who belong to the specified <paramref name="entityId"/>.</returns>
        Task<IList<MetadataField<TKey>>> GetFieldsInTypeAsync(TKey entityId, CancellationToken cancellationToken);
   }
}
